package com.zzjson.se.control;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Locale;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;

/**
 * <p>****************************************************************************</p>
 * <p><b>Copyright © 2010-2020 shuncom team All Rights Reserved<b></p>
 * <ul style="margin:15px;">
 * <li>Description : com.zzjson.se</li>
 * <li>Version     : 1.0.0</li>
 * <li>Creation    : 2020年04月08日</li>
 * <li>@author     : zzy0_0</li>
 * </ul>
 * <p>****************************************************************************</p>
 */
public class EncodedControl extends ResourceBundle.Control {
	private final String encoding;

	public EncodedControl(String encoding) {
		this.encoding = encoding;
	}

	public EncodedControl() {
		this.encoding = "utf-8";
	}

	@Override
	public ResourceBundle newBundle(String baseName, Locale locale, String format,
									ClassLoader loader, boolean reload)
			throws IllegalAccessException, InstantiationException, IOException {
		String bundleName = toBundleName(baseName, locale);
		ResourceBundle bundle = null;
		if (format.equals("java.class")) {
			try {
				@SuppressWarnings("unchecked")
				Class<? extends ResourceBundle> bundleClass
						= (Class<? extends ResourceBundle>) loader.loadClass(bundleName);

				// If the class isn't a ResourceBundle subclass, throw a
				// ClassCastException.
				if (ResourceBundle.class.isAssignableFrom(bundleClass)) {
					bundle = bundleClass.newInstance();
				} else {
					throw new ClassCastException(bundleClass.getName()
							+ " cannot be cast to ResourceBundle");
				}
			} catch (ClassNotFoundException e) {
			}
		} else if (format.equals("java.properties")) {
			final String resourceName = toResourceName0(bundleName, "properties");
			if (resourceName == null) {
				return bundle;
			}
			final ClassLoader classLoader = loader;
			final boolean reloadFlag = reload;
			InputStream stream = null;
			try {
				stream = AccessController.doPrivileged(
						new PrivilegedExceptionAction<InputStream>() {
							@Override
							public InputStream run() throws IOException {
								InputStream is = null;
								if (reloadFlag) {
									URL url = classLoader.getResource(resourceName);
									if (url != null) {
										URLConnection connection = url.openConnection();
										if (connection != null) {
											// Disable caches to get fresh data for
											// reloading.
											connection.setUseCaches(false);
											is = connection.getInputStream();
										}
									}
								} else {
									is = classLoader.getResourceAsStream(resourceName);
								}
								return is;
							}
						});
			} catch (PrivilegedActionException e) {
				throw (IOException) e.getException();
			}
			Reader reader = null;
			if (stream != null) {
				try {
					reader = new InputStreamReader(stream, encoding);

					bundle = new PropertyResourceBundle(reader);
				} finally {
					reader.close();
					stream.close();
				}
			}
		} else {
			throw new IllegalArgumentException("unknown format: " + format);
		}
		return bundle;
	}

	private String toResourceName0(String bundleName, String suffix) {
		// application protocol check
		if (bundleName.contains("://")) {
			return null;
		} else {
			return toResourceName(bundleName, suffix);
		}
	}
}
